package com.hotacorp.opencloud.flowservice.service.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.repository.DeploymentBuilder;
import org.camunda.bpm.engine.repository.DeploymentQuery;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.repository.ProcessDefinitionQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.hotacorp.opencloud.common.mybatisplus.PageConstant;
import com.hotacorp.opencloud.common.mybatisplus.PageData;
import com.hotacorp.opencloud.flowservice.dto.DeployDetailInfo;
import com.hotacorp.opencloud.flowservice.dto.DeployInfo;
import com.hotacorp.opencloud.flowservice.dto.DeployReq;
import com.hotacorp.opencloud.flowservice.dto.PorcDefInfo;
import com.hotacorp.opencloud.flowservice.service.DeploymentHandler;

/**
 * 流程发布接口实现
 * @author lwg
 *
 */
@Component
public class DeploymentHandlerImpl implements DeploymentHandler {

	@Autowired
	private RepositoryService repositoryService;
	
	@Override
	public void create(String tenantid, DeployReq request) throws Exception {
		DeploymentBuilder builder = repositoryService.createDeployment();
		builder.tenantId(tenantid);
		builder.name(request.getName());
		builder.source(request.getSource());
		builder.addInputStream(request.getName() + ".bpmn", new ByteArrayInputStream(request.getData()));
		builder.enableDuplicateFiltering(true);
		builder.deployWithResult();
	}

	@Override
	public PageData query(Map<String, Object> params) throws Exception {
        //分页参数
        int curPage = 1;
        int limit = 10;

        if(params.get(PageConstant.PAGE) != null){
            curPage = Integer.parseInt((String)params.get(PageConstant.PAGE));
        }
        if(params.get(PageConstant.LIMIT) != null){
            limit = Integer.parseInt((String)params.get(PageConstant.LIMIT));
        }
        //排序字段
        String orderField = (String)params.get(PageConstant.PROP);
        //排序方式
        String order = (String)params.get(PageConstant.ORDER);

		DeploymentQuery query = repositoryService.createDeploymentQuery();
		if (StringUtils.isNotBlank((String)params.get("after"))) query.deploymentAfter(DateUtils.parseDate((String)params.get("after"), "yyyy-MM-dd HH:mm:ss"));
		if (StringUtils.isNotBlank((String)params.get("before"))) query.deploymentBefore(DateUtils.parseDate((String)params.get("before"), "yyyy-MM-dd HH:mm:ss"));
		if (StringUtils.isNotBlank((String)params.get("id"))) query.deploymentId((String)params.get("id"));
		if (StringUtils.isNotBlank((String)params.get("name"))) query.deploymentName((String)params.get("name"));
		query.tenantIdIn((String)params.get("tenantid"));
        //前端字段排序
        if(StringUtils.isNotBlank(orderField) && StringUtils.isNotBlank(order)){
        	if ("id".equals(orderField)) query.orderByDeploymentId();
        	else if ("name".equals(orderField))  query.orderByDeploymentName();
        	else query.orderByDeploymentTime();
            if(PageConstant.ASC.equalsIgnoreCase(order)) {
            	query.asc();
            }else {
            	query.desc();
            }
        }
        int reccount = (int) query.count();
        List<Deployment> list = query.listPage((curPage-1)*limit, limit);
        List<DeployInfo> list1 = new ArrayList<>();
        list.forEach(action->{
        	DeployInfo retyDeployInfo = new DeployInfo();
        	retyDeployInfo.setId(action.getId());
        	retyDeployInfo.setDeploymentTime(action.getDeploymentTime());
        	retyDeployInfo.setName(action.getName());
        	retyDeployInfo.setSource(action.getSource());
        	list1.add(retyDeployInfo);
        });
		return new PageData(list1, reccount, limit, curPage);
	}

	@Override
	public void delete(String tenantid, String[] deploymentIds) {
		if (deploymentIds != null) {
			for(String deploymentId:deploymentIds) {
				DeploymentQuery query = repositoryService.createDeploymentQuery();
				query.deploymentId(deploymentId);
				query.tenantIdIn(tenantid);
				if (query.singleResult() != null) repositoryService.deleteDeployment(deploymentId);
			}
		}
		
	}

	@Override
	public PageData queryProcDef(Map<String, Object> params) throws Exception {
        //分页参数
        int curPage = 1;
        int limit = 10;

        if(params.get(PageConstant.PAGE) != null){
            curPage = Integer.parseInt((String)params.get(PageConstant.PAGE));
        }
        if(params.get(PageConstant.LIMIT) != null){
            limit = Integer.parseInt((String)params.get(PageConstant.LIMIT));
        }
        //排序字段
        String orderField = (String)params.get(PageConstant.PROP);
        //排序方式
        String order = (String)params.get(PageConstant.ORDER);

		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
		query.tenantIdIn((String)params.get("tenantid"));
		if (StringUtils.isNotBlank((String)params.get("last"))) query.latestVersion();
		if (StringUtils.isNotBlank((String)params.get("id"))) query.processDefinitionId((String)params.get("id"));
		if (StringUtils.isNotBlank((String)params.get("deploymentId"))) query.deploymentId((String)params.get("deploymentId"));
		if (StringUtils.isNotBlank((String)params.get("name"))) query.processDefinitionNameLike((String)params.get("name"));
		if (StringUtils.isNotBlank((String)params.get("key"))) query.processDefinitionKey((String)params.get("key"));
        //前端字段排序
        if(StringUtils.isNotBlank(orderField) && StringUtils.isNotBlank(order)){
        	if ("id".equals(orderField)) query.orderByProcessDefinitionId();
        	else if ("name".equals(orderField))  query.orderByProcessDefinitionName();
        	else if ("deploymentId".equals(orderField))  query.orderByDeploymentId();
        	else if ("key".equals(orderField))  query.orderByProcessDefinitionKey();
        	else query.orderByDeploymentId();
            if(PageConstant.ASC.equalsIgnoreCase(order)) {
            	query.asc();
            }else {
            	query.desc();
            }
        }
        int reccount = (int) query.count();
        List<ProcessDefinition> list = query.listPage((curPage-1)*limit, limit);
        List<PorcDefInfo> list1 = new ArrayList<>();
        list.forEach(action->{
        	PorcDefInfo retyDeployInfo = new PorcDefInfo();
        	retyDeployInfo.setId(action.getId());
        	retyDeployInfo.setCategory(action.getCategory());;
        	retyDeployInfo.setName(action.getName());
        	retyDeployInfo.setDeploymentId(action.getDeploymentId());
        	retyDeployInfo.setDescription(action.getDescription());
        	retyDeployInfo.setKey(action.getKey());
        	retyDeployInfo.setVersion(action.getVersion());
        	retyDeployInfo.setSuspended(action.isSuspended());
        	retyDeployInfo.setStartableInTasklist(action.isStartableInTasklist());
        	list1.add(retyDeployInfo);
        });
		return new PageData(list1, reccount, limit, curPage);

	}

	@Override
	public void deleteProcDef(String tenantid, String[] procdefIds) {
		if (procdefIds != null) {
			for(String deploymentId:procdefIds) {
				ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
				query.processDefinitionId(deploymentId);
				query.tenantIdIn(tenantid);
				if (query.singleResult() != null) repositoryService.deleteProcessDefinition(deploymentId);
			}
		}
	}

	@Override
	public InputStream getBpmn(String tenantid, String deploymentId) {
		Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).tenantIdIn(tenantid).singleResult();
		if (deployment != null) {
			String resourceid = "";
			List<String> assList = repositoryService.getDeploymentResourceNames(deploymentId);
			if (assList.size() > 0) resourceid = assList.get(0);
			return repositoryService.getResourceAsStream(deploymentId, resourceid);
		} else {
			throw new RuntimeException("没有找到此模型");
		}
	}

	@Override
	public DeployDetailInfo getDeployBpmn(String tenantid, String deploymentId) throws Exception {
		DeploymentQuery query = repositoryService.createDeploymentQuery();
		Deployment deployment = query.deploymentId(deploymentId).tenantIdIn(tenantid).singleResult();
		if (deployment != null) {
			DeployDetailInfo info = new DeployDetailInfo();
			info.setId(deployment.getId());
			info.setDeploymentTime(deployment.getDeploymentTime());
			info.setName(deployment.getName());
			info.setSource(deployment.getSource());
			String resourceid = "";
			List<String> assList = repositoryService.getDeploymentResourceNames(deploymentId);
			if (assList.size() > 0) resourceid = assList.get(0);
			InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceid);
			ByteArrayOutputStream result = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int length;
			while ((length = inputStream.read(buffer)) != -1) {
			    result.write(buffer, 0, length);
			}
			info.setBpmnXml(result.toString("UTF-8"));
			return info;
		}
		return null;
	}

	@Override
	public void suspendProcDef(String tenantid, String[] procdefIds) {
		if (procdefIds != null) {
			for(String deploymentId:procdefIds) {
				ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
				query.processDefinitionId(deploymentId);
				query.tenantIdIn(tenantid);
				if (query.singleResult() != null) repositoryService.suspendProcessDefinitionById(deploymentId);
			}
		}
	}

	@Override
	public void activatesProcDef(String tenantid, String[] procdefIds) {
		if (procdefIds != null) {
			for(String deploymentId:procdefIds) {
				ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
				query.processDefinitionId(deploymentId);
				query.tenantIdIn(tenantid);
				if (query.singleResult() != null) repositoryService.activateProcessDefinitionById(deploymentId);
			}
		}
	}

	@Override
	public InputStream getProcDefBpmn(String tenantid, String procdefId) {
		ProcessDefinition dddd = repositoryService.createProcessDefinitionQuery().tenantIdIn(tenantid).processDefinitionId(procdefId).singleResult();
		if (dddd != null) {
			return repositoryService.getResourceAsStream(dddd.getDeploymentId(), dddd.getResourceName());
		} else {
			throw new RuntimeException("没有找到此模型");
		}
	}

}
